package db

import (
	"core/config"
	"core/datetime"
	"time"

	"github.com/dubbogo/gost/log/logger"
	"gorm.io/driver/mysql"
	"gorm.io/driver/sqlite"
	"gorm.io/driver/sqlserver"

	"strings"

	"gorm.io/gorm"
	"gorm.io/gorm/schema"
	"gorm.io/plugin/dbresolver"
)

var (
	Config   = &DbConfig{}
	DbMaster *gorm.DB
)

func OpenDb(cfg *DbConfig) (*gorm.DB, error) {
	switch Config.Driver {
	case "sqlserver":
		return openSqlServer(cfg)
	case "sqllite":
		return openSqllite(cfg)
	default:
		return openMySql(cfg)
	}
}
func openMySql(cfg *DbConfig) (*gorm.DB, error) {
	db, err := gorm.Open(mysql.Open(cfg.Dsn),
		&gorm.Config{
			NamingStrategy: schema.NamingStrategy{
				SingularTable: true,
				NoLowerCase:   false,
			},
			Logger:                 NewGormLogger(cfg),
			SkipDefaultTransaction: true,
		})
	if err != nil {
		return nil, err

	} else {
		//logger.Info("打开数据库成功")
	}
	//db.Use(&DbFieldPlugin{})  暂时不需要，update 会重复字段
	if strings.TrimSpace(cfg.ReadDsn) != "" {
		db.Use(dbresolver.Register(dbresolver.Config{
			// use `db2` as sources, `db3`, `db4` as replicas
			//Sources:  []gorm.Dialector{mysql.Open("db2_dsn")},
			Replicas: []gorm.Dialector{mysql.Open(cfg.ReadDsn)},
			// sources/replicas load balancing policy
			Policy: dbresolver.RandomPolicy{},
			// print sources/replicas mode in logger
			TraceResolverMode: true,
		}))
	}
	return db, nil
}

func openSqlServer(cfg *DbConfig) (*gorm.DB, error) {
	var f = sqlserver.Open(cfg.Dsn)
	db, err := gorm.Open(f,
		&gorm.Config{
			NamingStrategy: schema.NamingStrategy{
				SingularTable: true,
				NoLowerCase:   false,
			},
			Logger:                 NewGormLogger(cfg),
			SkipDefaultTransaction: true,
		})
	if err != nil {
		return nil, err

	} else {

	}
	//db.Use(&DbFieldPlugin{})  暂时不需要，update 会重复字段
	if strings.TrimSpace(cfg.ReadDsn) != "" {
		db.Use(dbresolver.Register(dbresolver.Config{
			// use `db2` as sources, `db3`, `db4` as replicas
			//Sources:  []gorm.Dialector{mysql.Open("db2_dsn")},
			Replicas: []gorm.Dialector{mysql.Open(cfg.ReadDsn)},
			// sources/replicas load balancing policy
			Policy: dbresolver.RandomPolicy{},
			// print sources/replicas mode in logger
			TraceResolverMode: true,
		}))
	}
	return db, nil
}

func openSqllite(cfg *DbConfig) (*gorm.DB, error) {
	var f = sqlite.Open(cfg.Dsn)
	db, err := gorm.Open(f,
		&gorm.Config{
			NamingStrategy: schema.NamingStrategy{
				SingularTable: true,
				NoLowerCase:   false,
			},
			Logger:                 NewGormLogger(cfg),
			SkipDefaultTransaction: true,
		})
	if err != nil {
		return nil, err

	} else {

	}
	return db, nil
}
func DbMasterNow() (time.Time, error) {
	var sql = "SELECT now()"
	var r = time.Time{}
	switch Config.Driver {
	case "sqlserver":
		sql = "SELECT getdate()"
		tx := DbMaster.Raw(sql).Scan(&r)
		return r, tx.Error

	case "sqllite":
		var currentTime string
		sql = "select datetime(CURRENT_TIMESTAMP,'localtime');"
		tx := DbMaster.Raw(sql).Scan(&currentTime)
		if tx.Error != nil {
			return r, tx.Error
		} else {
			r, err := datetime.ParseDateTime(currentTime)
			return r, err
		}

	default:
		tx := DbMaster.Raw(sql).Scan(&r)
		return r, tx.Error
	}

}
func init() {
	config.ConfigViper.UnmarshalKey("db", Config)
	if Config.Dsn != "" {
		db, err := OpenDb(Config)
		if err != nil {
			logger.Errorf("连接数据库 %v 失败 %v", Config.Driver, err)
		} else {
			logger.Infof("连接数据库 %v 成功", Config.Driver)
			DbMaster = db
		}
	}

}
